package com.lakeworks.service.impl;

import com.lakeworks.common.constant.HttpStatus;
import com.lakeworks.common.domain.channel.*;
import com.lakeworks.common.enums.*;
import com.lakeworks.common.exception.base.channel.ThirdChannelException;
import com.lakeworks.common.exception.response.ResponseException;
import com.lakeworks.common.utils.DateUtils;
import com.lakeworks.common.utils.SecurityUtils;
import com.lakeworks.domain.*;
import com.lakeworks.event.*;
import com.lakeworks.mapper.OprMerchandiseMapper;
import com.lakeworks.mapper.OprProductMapper;
import com.lakeworks.mapper.SysProductMapper;
import com.lakeworks.service.*;
import com.lakeworks.service.api.MerchantAsync;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Caching;
import org.springframework.context.ApplicationContext;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static com.alibaba.fastjson.JSON.toJSONString;
import static com.lakeworks.common.enums.FlagType.DELETE;
import static com.lakeworks.common.utils.bean.BeanUtils.copyBeanProp;
import static com.lakeworks.common.utils.bean.DeepCopyUtil.transform;
import static com.lakeworks.common.utils.bean.DeepCopyUtil.transformList;
import static com.lakeworks.service.impl.OperateRecordUtil.commonImportRecord;
import static com.lakeworks.service.impl.OperateRecordUtil.saveImportRecord;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import static java.util.Optional.ofNullable;
import static org.apache.commons.lang3.StringUtils.*;
import static org.springframework.http.ResponseEntity.*;

/**
 * @Author: Auxps
 * @Date: 2023/3/9
 * Description:
 * 均需保证接口幂等
 * 三方渠道对接中  ThirdChannelException、RuntimeException 均已做异常处理
 * ThirdChannelException 渠道传入数据异常  响应状态状态码400 并返回errcode、errmsg
 * RuntimeException  内部异常 只响应状态码500
 */
@Slf4j
@Service
public class ThirdChannelServiceImpl implements IThirdChannelService {

    @Autowired
    private IOprPickupService oprPickupService;

    @Autowired
    private IOprShipmentService oprShipmentService;

    @Autowired
    private ISysChannelService sysChannelService;

    @Autowired
    private IOprProductService oprProductService;

    @Autowired
    private IOprMerchandiseService oprMerchandiseService;

    @Autowired
    private IStaPickupService staPickupService;

    @Autowired
    private IOprAttachmentService oprAttachmentService;

    @Autowired
    private MerchantAsync merchantAsync;

    @Resource
    private SysProductMapper sysProductMapper;

    @Resource
    private OprMerchandiseMapper oprMerchandiseMapper;

    @Resource
    private ISysAttachmentService sysAttachmentService;

    @Resource
    private OprProductMapper oprProductMapper;

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private IStaProductService productService;


    private static ArrayList<String> expressStatus;

    static {
        expressStatus =  new ArrayList<>();
        expressStatus.add("PICKED");
        expressStatus.add("SHIPPING");
        expressStatus.add("DELIVERING");
        expressStatus.add("DELIVERED");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity pickupImport(String pickupNo, PickupImport pickupImport) {
        log.info("入厂单导入，pickupNo: [{}]，pickupImport: [{}]", pickupNo, toJSONString(pickupImport));
        SysChannel sysChannel = getSysChannel();

        if (oprPickupService.selectByChannelIdAndChPickupNo(sysChannel.getId(), pickupNo) != null)
            return status(HttpStatus.CREATED).build();
        OprPickup oprPickup = transform(pickupImport, OprPickup.class);

        oprPickup.setStatus(PickupType.PENDING.getValue())
                .setChannelId(sysChannel.getId())
                .setChPickupNo(pickupNo)
                .setQuantity(pickupImport.getItems().size())
                .setCreateBy(sysChannel.getName())
                .setModifyBy(sysChannel.getName());

        oprPickup.setFlag(1);
        if (pickupImport.isTreat()) {
            oprPickup.setFlag(oprPickup.getFlag() | WorkType.TREAT.value());
        }
        if (pickupImport.isDivert()) {
            oprPickup.setFlag(oprPickup.getFlag() | WorkType.DIVERT.value());
        }
        if(pickupImport.isRecall()){
            oprPickup.setFlag(oprPickup.getFlag() | WorkType.RETURN.value());
        }
//        if(pickupImport.isRecycle()){
//            oprPickup.setFlag(oprPickup.getFlag() | WorkType.RECYCLE.value());
//        }
        oprPickupService.insertOprPickup(oprPickup);
        saveImportRecord(StatusRecordEnum.PICKUP, oprPickup.getId(), PickupType.PENDING.getValue());

        transformList(pickupImport.getItems(), OprMerchandise.class)
                .forEach(oprMerchandise -> {
                    oprMerchandise.setPickupId(oprPickup.getId())
                            .setCreateBy(sysChannel.getName())
                            .setModifyBy(sysChannel.getName());
                    oprMerchandiseService.insertOprMerchandise(oprMerchandise);
                });
        return status(HttpStatus.CREATED).build();
    }

    @Override
    public ResponseEntity pickupUpdate(String pickupNo, ExpressAlter expressAlter) {
        log.info("入厂单信息修改，pickupNo: [{}]，expressAlter: [{}]", pickupNo, toJSONString(expressAlter));
        OprPickup oprPickup = getOprPickup(pickupNo);

        ofNullable(expressAlter.getCarrier()).filter(StringUtils::hasText).ifPresent(oprPickup::setCarrier);
        ofNullable(expressAlter.getExpressNo()).filter(StringUtils::hasText).ifPresent(oprPickup::setExpressNo);
        ofNullable(expressAlter.getEta()).filter(Objects::nonNull).ifPresent(oprPickup::setEta);

        oprPickupService.updateOprPickup(oprPickup);
        return noContent().build();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity deletePickup(String pickupNo) {
        log.info("入厂单删除，pickupNo: [{}]", pickupNo);
        OprPickup oprPickup = getOprPickup(pickupNo);
        oprPickupService.pickupCancel(oprPickup.getId());
        oprPickup.setFlag(DELETE.value());
        oprPickupService.updateOprPickup(oprPickup);
        staPickupService.deleteStaPickupByPickupId(oprPickup.getId());
        return noContent().build();
    }



    @Override
    public ResponseEntity pickupCancel(String pickupNo) {
        log.info("入厂单取消，pickupNo: [{}]", pickupNo);
        OprPickup oprPickup = getOprPickup(pickupNo);
        if(equalsAny(oprPickup.getStatus(),PickupType.VERIFY.getValue(),PickupType.RECEIVED.getValue())){
            throw new ThirdChannelException(ChannelErrorEnum.PICKUP_NOT_FIND);
        }
        oprPickup.setStatus(PickupType.CANCEL.getValue());
        oprPickupService.updateOprPickup(oprPickup);
        saveImportRecord(StatusRecordEnum.PICKUP, oprPickup.getId(), PickupType.CANCEL.getValue());
        return noContent().build();
    }


    @Override
    //@Transactional(rollbackFor = Exception.class)
    public ResponseEntity syncShipment(String shipmentNo, ShipmentImport shipmentImport) {
        log.info("下发出厂单，shipmentNo：[{}]，shipmentImport: [{}]", shipmentNo, toJSONString(shipmentImport));
        SysChannel sysChannel = getSysChannel();
        //已经下发过出厂单
        if (oprShipmentService.selectByChannelIdAndChShipmentNo(sysChannel.getId(), shipmentNo) != null)
            return status(HttpStatus.CREATED).build();

        List<String> barcodeList = shipmentImport.getBarcodeList();
        OprShipment oprShipment = new OprShipment()
                .setChannelId(sysChannel.getId())
                .setChShipmentNo(shipmentNo)
                .setOrderNo(oprPickupService.selectOrderNoByBarcode(barcodeList.get(0)))
                .setQuantity(barcodeList.size())
                .setStatus(ShipMentType.PENDING.getValue())
                .setComment(shipmentImport.getComment())
                .setCreateBy(sysChannel.getName())
                .setModifyBy(sysChannel.getName());
        if(shipmentImport.getRecycle() == null){
            shipmentImport.setRecycle(false);
        }
        if (shipmentImport.getRecycle()){
            oprShipment.setFlag(WorkType.RECYCLE.value());
        }
        oprShipmentService.insertOprShipment(oprShipment);
        //记录状态
        saveImportRecord(StatusRecordEnum.SHIPMENT, oprShipment.getId(), ShipMentType.PENDING.getValue());
        for (String barcode : barcodeList) {
            OprProduct oprProduct = oprProductService.queryByBarcode(barcode);
            if (isNull(oprProduct) || nonNull(oprProduct.getCompanionId()))
                throw new ThirdChannelException(ChannelErrorEnum.BARCODE_ERROR);
            //产品重复分配出厂单
            if (oprProduct.getShipmentId() != null)
                throw new ThirdChannelException(ChannelErrorEnum.BARCODE_REPEAT_ALLOCATE);
            OprProduct domain = new OprProduct().setShipmentId(oprShipment.getId()).setId(oprProduct.getId());
            if (shipmentImport.getRecycle()){
                domain.setFlag(WorkType.RECYCLE.value());
            }
            oprProductService.updateOprProduct(domain);
            oprProductService.updateByCompanionId(domain);
            //出厂单、产品 分配搁架
        }
        //触发入场单下发成功事件（向二次分配线推送整个出厂单衣物）
        log.info("触发入场单下发成功事件--shipmentNo:[{}]",shipmentNo);
        applicationContext.publishEvent(new DistributionEvent(this,shipmentNo,sysChannel.getId()));
        if (shipmentImport.getRecycle()){
            log.info("触发回收单执行流程事件");

            applicationContext.publishEvent(new RecycleEvent(this,oprShipment.getId(),barcodeList));
        }
        return status(HttpStatus.CREATED).build();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity express(String shipmentNo, ExpressInfo expressInfo) {
        log.info("下发物流信息，shipmentNo：[{}]，expressInfo: [{}]", shipmentNo, toJSONString(expressInfo));
        OprShipment oprShipment = getOprShipment(shipmentNo);
        boolean flag  = true;
        if (!isAllBlank(oprShipment.getCarrier(), oprShipment.getExpressNo(), oprShipment.getLabel()))
            flag = false;

        oprShipmentService.updateOprShipment(new OprShipment()
                .setCarrier(expressInfo.getCarrier())
                .setExpressNo(expressInfo.getExpressNo())
                .setLabel(expressInfo.getLabel())
                .setId(oprShipment.getId()));

        if (flag) {
            oprShipmentService.updateOprShipment(new OprShipment().setStatus(ShipMentType.TOPICK.getValue()).setId(oprShipment.getId()));
            saveImportRecord(StatusRecordEnum.SHIPMENT, oprShipment.getId(), ShipMentType.TOPICK.getValue());

            List<OprProduct> oprProducts = oprProductService.selectByShipmentId(oprShipment.getId());
//            if (oprProducts.stream().map(OprProduct::getStatus).anyMatch(not(OprProductType.PLACED.getValue()::equals)))
//                throw new ThirdChannelException(ChannelErrorEnum.NO_PUTWAY);

            OprPickup oprPickup = null;
            //出厂单中所有产品 status -> 待拣货
            for (OprProduct oprProduct : oprProducts) {
                oprProductService.updateByIdOrCompanionId(new OprProduct().setStatus(OprProductType.TOPICK.getValue()).setId(oprProduct.getId()));
                saveImportRecord(StatusRecordEnum.PRODUCT, oprProduct.getId(), OprProductType.TOPICK.getValue());
                if (oprPickup == null)
                    oprPickup = oprPickupService.selectOprPickupById(oprProduct.getPickupId());
                merchantAsync.backProductState(ProductStatus.builder()
                        .pickupNo(oprPickup.getChPickupNo())
                        .barcode(oprProduct.getBarcode())
                        .status(OprProductType.TOPICK.name())
                        .state(0).noWash(false).build(), oprPickup.getChannelId());
            }
            merchantAsync.backShipState(ShipmentStatus.builder().shipmentNo(oprShipment.getChShipmentNo()).status(ShipMentType.TOPICK.name()).build(), oprShipment.getChannelId());
            try {
                applicationContext.publishEvent(new PickingEvent(this, oprShipment.getId()));
            } catch (Exception e) {
                log.error("触发自动拣货中失败::error:[{}]", e);
            }
        }
        return status(HttpStatus.CREATED).build();
    }

    @Override
    public ResponseEntity getPickupInfo(String pickupNo) {
        OprPickup oprPickup = getOprPickup(pickupNo);
        List<ProductInfo> items = oprPickupService.pickupInfoById(oprPickup.getId());
        items.forEach(productInfo -> {
            productInfo.setStatus(OprProductType.instance(productInfo.getStatus()).name());
        });
        PickupInfo pickupInfo = transform(oprPickup, PickupInfo.class)
                .setStatus(PickupType.instance(oprPickup.getStatus()).name())
                .setItems(items);

        return ok(pickupInfo);
    }

    @Override
    public ResponseEntity getProductInfo(String pickupNo, String barcode) {
        OprPickup oprPickup = getOprPickup(pickupNo);

        OprProduct oprProduct = oprProductService.queryByBarcode(barcode);
        if (isNull(oprProduct) || !oprProduct.getPickupId().equals(oprPickup.getId()))
            throw new ThirdChannelException(ChannelErrorEnum.BARCODE_ERROR);

        ProductInfo productInfo = oprPickupService.productInfoById(oprPickup.getId(), barcode);
        productInfo.setStatus(OprProductType.instance(productInfo.getStatus()).name());

        return ok(productInfo);
    }

    @Override
    public ResponseEntity getShipmentInfo(String shipmentNo) {
        OprShipment oprShipment = getOprShipment(shipmentNo);
        ShipmentInfo shipmentInfo = transform(oprShipment, ShipmentInfo.class);
        List<ProductItem> items = oprShipmentService.productItemById(oprShipment.getId());

        items.forEach(productItem -> productItem.setStatus(OprProductType.instance(productItem.getStatus()).name()));
        shipmentInfo.setStatus(ShipMentType.instance(oprShipment.getStatus()).name());
        shipmentInfo.setItems(items);

        return ok(shipmentInfo);
    }

    /**
     * 添加系统产品信息
     *
     * @return
     */
    @Override
    @Caching(evict = {
            @CacheEvict(value = "sysProducts", allEntries = true),
            @CacheEvict(value = "product",allEntries = true)
    })
    public ResponseEntity addSysProduct(String code, SysProductInfo sysProductInfo) {
        log.info("添加系统产品信息,code：[{}]，sysProductInfo：[{}]", code, toJSONString(sysProductInfo));
        SysChannel sysChannel = getSysChannel();
        SysProduct build = SysProduct.builder().build();
        copyBeanProp(build, sysProductInfo);
        build.setCode(code);
        build.setChannelId(sysChannel.getId());
        build.setCreateBy(sysChannel.getName());
        build.setModifyBy(sysChannel.getName());
        SysProduct product = sysProductMapper.selectSysProductByCode(build);
        int num = 0;
        if(product != null){
            num = sysProductMapper.updateSysProductInfo(build);
        }else {
            num = sysProductMapper.insertSysProduct(build);
        }
        if (num == 0) {
            throw new RuntimeException("入厂单保存失败");
        }
        return status(HttpStatus.CREATED).build();
    }

    /**
     * 修改系统产品信息
     *
     * @return
     */
    @Override
    @Caching(evict = {
            @CacheEvict(value = "sysProducts", allEntries = true),
            @CacheEvict(value = "product",allEntries = true)
    })
    public ResponseEntity updateSysProduct(String code, SysProductInfo sysProductInfo) {
        log.info("修改系统产品信息,code：[{}]，sysProductInfo：[{}]", code, toJSONString(sysProductInfo));
        SysChannel sysChannel = getSysChannel();
        SysProduct build = SysProduct.builder().build();
        copyBeanProp(build, sysProductInfo);
        build.setCode(code);
        build.setCreateBy(sysChannel.getName());
        build.setModifyBy(sysChannel.getName());
        int num = sysProductMapper.updateSysProductInfo(build);
        if (num == 0) {
            throw new ThirdChannelException(ChannelErrorEnum.SYSPRODUCT_NOT_FIND);
        }
        return status(HttpStatus.NO_CONTENT).build();
    }

    /**
     * 删除系统产品信息
     *
     * @return
     */
    @Override
    @Caching(evict = {
            @CacheEvict(value = "sysProducts", allEntries = true),
            @CacheEvict(value = "product",allEntries = true)
    })
    public ResponseEntity deleteSysProduct(String code) {
        log.info("删除系统产品信息,code：[{}]", code);
        SysChannel sysChannel = getSysChannel();
        SysProduct build = SysProduct.builder().channelId(sysChannel.getId()).code(code).build();
        build.setFlag(DELETE.value());
        int num = sysProductMapper.updateSysProductInfo(build);
        if (num == 0) {
            throw new ThirdChannelException(ChannelErrorEnum.SYSPRODUCT_NOT_FIND);
        }
        return status(HttpStatus.NO_CONTENT).build();
    }

    @Override
    public ResponseEntity updateMerchandises(String pickupNo, String code) {
        log.info("修改入场单商品,pickupNo：[{}]，merchandises：[{}]", pickupNo, toJSONString(code));
        SysChannel sysChannel = getSysChannel();
        OprPickup pickup = oprPickupService.selectByChannelIdAndChPickupNo(sysChannel.getId(), pickupNo);
        if (pickup == null || equalsAny(pickup.getStatus(), PickupType.VERIFY.getValue(), PickupType.RECEIVED.getValue())) {
            throw new ThirdChannelException(ChannelErrorEnum.PICKUPNO_INVALID);
        }
        if (isBlank(code)) {
            throw new ThirdChannelException(ChannelErrorEnum.MERCHANDISE_CODE_BLANK);
        }
        OprMerchandise merchandise = new OprMerchandise();
        merchandise.setPickupId(pickup.getId());
        merchandise.setCode(code);
        List<OprMerchandise> merchandises = oprMerchandiseMapper.selectOprMerchandiseList(merchandise);
        if (merchandises.isEmpty()) {
            throw new ThirdChannelException(ChannelErrorEnum.MERCHANDISE_NUM_ERROR);
        }
        OprMerchandise oprMerchandise = merchandises.get(0);
        oprMerchandise.setFlag(DELETE.value());
        oprMerchandiseMapper.updatePickUpMerchandise(oprMerchandise);
        OprPickup build = OprPickup.builder().quantity(pickup.getQuantity() - 1).build();
        build.setId(pickup.getId());
        oprPickupService.updateOprPickup(build);
        return status(HttpStatus.SUCCESS).build();
    }

    @Override
    public ResponseEntity updateProducts(String shipmentNo, List<String> bracodes) {
        log.info("修改出厂单产品,shipmentNo：[{}]，bracodes：[{}]", shipmentNo, toJSONString(bracodes));
        SysChannel sysChannel = getSysChannel();
        OprShipment shipment = oprShipmentService.selectByChannelIdAndChShipmentNo(sysChannel.getId(), shipmentNo);
        if (shipment == null) {
            throw new ThirdChannelException(ChannelErrorEnum.SHIPMENTNO_INVALID);
        }
        if (bracodes.isEmpty()) {
            throw new ThirdChannelException(ChannelErrorEnum.BARCODE_ITEMS_BLANK);
        }
        bracodes.forEach(b -> {
            oprProductMapper.updateProductShipmentId(b);
        });
        if (oprProductMapper.queryByShipmentId(shipment.getId()).stream().map(OprProduct::getStatus).allMatch(OprProductType.PLACED.getValue()::equals)) {
            log.info("出厂单 {} 剩余产品全部已上架",shipmentNo);
            oprShipmentService.updateOprShipment(new OprShipment().setStatus(ShipMentType.ORDERING.getValue()).setId(shipment.getId()));
            commonImportRecord(StatusRecordEnum.SHIPMENT, shipment.getId(), ShipMentType.ORDERING.getValue());
            //回写出厂单状态
            merchantAsync.backShipState(ShipmentStatus.builder().shipmentNo(shipmentNo).status(ShipMentType.ORDERING.name()).build(), shipment.getChannelId());
        }
        shipment.setUpdateTime(DateUtils.getNowDate());
        List<OprProduct> productList = oprProductService.selectByShipmentId(shipment.getId());
        if(productList.isEmpty()){
            shipment.setFlag(DELETE.value());
        }
        oprShipmentService.updateOprShipment(shipment);
        return status(HttpStatus.SUCCESS).build();
    }

    @Override
    public ResponseEntity addMerchandises(String pickupNo, List<MerchandiseItem> merchandises) {
        log.info("添加入厂单商品,pickupNo：[{}]，merchandises：[{}]", pickupNo, toJSONString(merchandises));
        SysChannel sysChannel = getSysChannel();
        OprPickup pickup = oprPickupService.selectByChannelIdAndChPickupNo(sysChannel.getId(), pickupNo);
        if (pickup == null || equalsAny(pickup.getStatus(), PickupType.VERIFY.getValue(), PickupType.RECEIVED.getValue())) {
            throw new ThirdChannelException(ChannelErrorEnum.PICKUPNO_INVALID);
        }
        if (merchandises.isEmpty()) {
            throw new ThirdChannelException(ChannelErrorEnum.MERCHANDISE_CODE_BLANK);
        }
        merchandises.forEach(m -> {
            OprMerchandise merchandise = new OprMerchandise();
            merchandise.setPickupId(pickup.getId());
            merchandise.setCode(m.getCode());
            merchandise.setName(m.getName());
            merchandise.setComment(m.getComment());
            merchandise.setCreateBy(sysChannel.getName());
            merchandise.setModifyBy(sysChannel.getName());
            oprMerchandiseMapper.insertOprMerchandise(merchandise);
        });
        return status(HttpStatus.SUCCESS).header("Connection","close").build();
    }

    @Override
    public ResponseEntity holdOrder(String orderNo) {
        String code = oprProductService.holdingOrder(orderNo, false);
        if (!code.equals("success")) {
            throw new ResponseException(code);
        }
        return status(HttpStatus.SUCCESS).build();
    }


    /**
     * 添加系统瑕疵信息
     * @return
     */
   /* @Override
    public ResponseEntity addSysDefetive(Long id,SysDefectiveInfo sysDefectiveInfo) {
        SysDefective build = SysDefective.builder().build();
        copyBeanProp(build,sysDefectiveInfo);
        build.setId(id);
        build.setCreateBy(getUserName());
        build.setModifyBy(getUserName());
        sysDefectiveMapper.insertSysDefective(build);
        return ResponseEntity.status(HttpStatus.SUCCESS).build();
    }*/

    /**
     * 修改系统瑕疵信息
     * @return
     */
   /* @Override
    public ResponseEntity updateSysDefetive(Long id,SysDefectiveInfo sysDefectiveInfo) {
        SysDefective build = SysDefective.builder().build();
        copyBeanProp(build,sysDefectiveInfo);
        build.setId(id);
        build.setCreateBy(getUserName());
        build.setModifyBy(getUserName());
        return ResponseEntity.ok(sysDefectiveMapper.updateSysDefective(build));
    }*/

    /**
     * 删除系统瑕疵信息
     *
     * @return
     */
    /*@Override
    public ResponseEntity deleteSysDefetive(Long id) {
        SysDefective build = SysDefective.builder().build();
        build.setId(id);
        build.setFlag(FlagType.DELETE.value());
        return ResponseEntity.ok().build();
    }*/

    private OprPickup getOprPickup(String pickupNo) {
        return ofNullable(oprPickupService.selectByChannelIdAndChPickupNo(getSysChannel().getId(), pickupNo))
                .orElseThrow(() -> new ThirdChannelException(ChannelErrorEnum.PICKUP_NOT_FIND));
    }

    private OprShipment getOprShipment(String shipmentNo) {
        return ofNullable(oprShipmentService.selectByChannelIdAndChShipmentNo(getSysChannel().getId(), shipmentNo))
                .orElseThrow(() -> new ThirdChannelException(ChannelErrorEnum.SHIPMENT_NOT_FIND));
    }

    @Override
    public SysChannel getSysChannel() {
        SysChannelAuth sysChannelAuth = (SysChannelAuth) SecurityUtils.getPrincipal();
        return sysChannelService.selectSysChannelById(sysChannelAuth.getChannelId());
    }

    @Override
    public ResponseEntity expressStatus(ExpressVo expressVo) {
        log.info("同步物流状态,expressVo：{}",expressVo);
        if(ExpressStatus.DELIVERED.name().equals(expressVo.getStatus())){
            List<OprPickup> pickups = oprPickupService.selectOprPickupList(OprPickup.builder().expressNo(expressVo.getExpressNo()).status(PickupType.PENDING.getValue()).build());
            if(!pickups.isEmpty()){
                log.info("触发自动签收：{}",pickups.get(0));
                applicationContext.publishEvent(new CheckEvent(this, pickups.get(0).getExpressNo())); //触发准备核查事件
            }
        }else if(expressStatus.contains(expressVo.getStatus())){
            List<OprShipment> oprShipments = oprShipmentService.selectShipmentList(OprShipment.builder().expressNo(expressVo.getExpressNo()).build());
            if(!oprShipments.isEmpty()){
                log.info("触发自动出厂：{}",oprShipments.get(0));
                applicationContext.publishEvent(new OutFactoryEvent(this, oprShipments.get(0).getExpressNo())); //触发自动出厂
            }
        }
        return status(HttpStatus.SUCCESS).build();
    }

    @Override
    public ResponseEntity statusByBarcode(String barcode) {
        log.info("查询产品作业记录，barcode：[{}]",barcode);
        return ok(productService.statusByBarcode(barcode));
    }

    @Override
    public ResponseEntity getBarcodes(QuaryVo quaryVo) {
        log.info("二次分配线查询出厂单数据");
        if(isAnyBlank(quaryVo.getStartTime(),quaryVo.getEndTime())){
           return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
        }
        if(quaryVo.getAttState() == null){
            quaryVo.setAttState(false);
        }
//        if(quaryVo.getEndTime().equals(quaryVo.getStartTime())){
//            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtils.YYYY_MM_DD_HH_MM_SS);
//            LocalDate date = LocalDate.parse(quaryVo.getEndTime(), formatter);
//            LocalDate nextDay = date.plusDays(1);
//            quaryVo.setEndTime(nextDay.format(formatter));
//        }
        return ok(oprShipmentService.queryShipmentsByDistribution(OprShipment.builder()
                .startTime(quaryVo.getStartTime())
                .channelId(ofNullable(sysChannelService.selectSysChannelByCode(quaryVo.getChannel())).map(SysChannel::getId).orElse(null))
                .endTime(quaryVo.getEndTime())
                .build()).stream().map(s -> ShipmentCloths.builder()
                .chShipmentNo(s.getChShipmentNo())
                .modify_at(s.getModifyAt())
                .bacodes(oprProductService.selectByShipmentIdExcludeCompanion(s.getId()).stream().map(p -> BarcodeInfo.builder()
                        .barcode(p.getBarcode())
                        .name(sysProductMapper.selectSysProductById(p.getProductId()).getName())
                        .attList(oprAttachmentService.selectByProductIdOrCompanionId(p.getId()).stream().filter(a->quaryVo.getAttState()).map(a -> AttachmentInfo.builder()
                                .attName(ofNullable(sysAttachmentService.selectSysAttachmentById(a.getAttachmentId())).map(SysAttachment::getName).orElse(null))
                                .barcode(a.getBarcode())
                                .build()).toList())
                        .build()).toList())
                .build()).toList());
    }

    @Override
    public ResponseEntity updateProductCode(String barcode, String code) {
        log.info("查询产品作业记录，barcode：[{}],code:[{}]",barcode,code);
        OprProduct product = oprProductService.queryByBarcode(barcode);
        if(product == null){
            throw new ThirdChannelException(ChannelErrorEnum.BARCODE_ERROR);
        }
        SysChannel sysChannel = getSysChannel();
        SysProduct sysProduct = sysProductMapper.selectSysProductByCode(SysProduct.builder().code(code).channelId(sysChannel.getId()).build());
        if(sysProduct == null){
            throw new ThirdChannelException(ChannelErrorEnum.PARAM_ERROR);
        }
        OprProduct build = OprProduct.builder().productId(sysProduct.getId()).build();
        build.setId(product.getId());
        oprProductService.updateOprProduct(build);
        return status(HttpStatus.SUCCESS).build();
    }
}
